﻿using System;
using GLWrap.MathExt;
using Sharp3D.Math.Core;
using Tao.OpenGl;
using GLWrap.SceneObjects.Line;
using System.Diagnostics;

namespace GLWrap.SceneObjects
{
    public class SimpleLine : BaseLine
    {
        private float _length;
        private float _yAngle;
        private float _xAngle;
        private GluQuadricObject _gluQuadricObject;

        public SimpleLine()
        {
            PointA = new Vector3F(0, 0, 0);
            PointB = new Vector3F(1, 1, 1);
        }

        protected override void InternalLineWillBeDrawn(GlSceneManager sceneManager)
        {
            Gl.glTranslatef(PointA.X, PointA.Y, PointA.Z);

            Gl.glRotatef(_yAngle, 0, 1, 0);
            Gl.glRotatef(-_xAngle, 1, 0, 0);

            Glu.gluCylinder(_gluQuadricObject.Quadric, Weight, Weight, _length, 25, 25);
        }

        protected override void InternalLineAttachedToScene(GlSceneManager sceneManager)
        {
            _gluQuadricObject = new GluQuadricObject();
        }

        protected override void InternalLineDetachedFromScene(GlSceneManager sceneManager)
        {
            _gluQuadricObject.Dispose();
        }

        protected override void InternalRecalculateLineForSceneManager(GlSceneManager sceneManager)
        {
            MarkAsClean();

            Vector3F line = PointB - PointA;

            _length = line.GetLength();

            var pA_ZX = new Vector3F(PointA.X, 0, PointA.Z);
            var pB_ZX = new Vector3F(PointB.X, 0, PointB.Z);

            var pA_YZ = new Vector3F(0, PointA.Y, PointA.Z);
            var pB_YZ = new Vector3F(0, PointB.Y, PointB.Z);

            Vector3F zxLine = pB_ZX - pA_ZX;
            Vector3F yzLine = pB_YZ - pA_YZ;

            var oZ = new Vector3F(0, 0, 1);

            _yAngle = 0;
            _xAngle = 0;

            if (!zxLine.GetLength().EqualWithEpsilan(0, 0.001f))
            {
                _yAngle = MathHelper.NormalizeAngle(MathHelper.GetDegreesBetweenVectors(oZ, zxLine)); // oY rotate

                while (_yAngle > (180.0 - _yAngle)) _yAngle = (float)(180.0 - _yAngle);

                Quarter yAngleQuarter = MathHelper.GetQuarter(new Vector2F(PointA.Z, PointA.X),
                                                   new Vector2F(PointB.Z, PointB.X));

                MathHelper.MoveAngleToQuarter(ref _yAngle, yAngleQuarter);
            }

            if (!yzLine.GetLength().EqualWithEpsilan(0, 0.001f))
            {
                if (!zxLine.GetLength().EqualWithEpsilan(0, 0.001f))
                    _xAngle = MathHelper.NormalizeAngle(MathHelper.GetDegreesBetweenVectors(line, zxLine)); // oX rotate
                else
                    _xAngle = MathHelper.NormalizeAngle(MathHelper.GetDegreesBetweenVectors(line, oZ)); // oX rotate

                while (_xAngle > (180.0 - _xAngle)) _xAngle = (float)(180.0 - _xAngle);

                Quarter xAngleQuarter = (PointB.Y - PointA.Y) > 0 ? Quarter.First : Quarter.Fourth;

                MathHelper.MoveAngleToQuarter(ref _xAngle, xAngleQuarter);
            }
        }
       
    }
}
